package com.dmc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.Assert;
import com.dmc.conf.Constant;
import com.dmc.dict.*;
import com.dmc.entity.BankInfo;
import com.dmc.entity.Message;
import com.dmc.mapper.*;
import com.dmc.model.*;
import com.dmc.service.CashOutOrderService;
import com.dmc.service.PayService;
import com.dmc.service.UserAccountService;
import com.dmc.service.UserBankCardService;
import com.dmc.util.DecimalUtil;
import com.dmc.util.util.OrderCodeUtil;
import com.dmc.util.util.SessionUtil;
import com.dmc.vo.BankCardVo;
import com.dmc.vo.CashOutOrdersVo;
import com.dmc.vo.DataTable;
import com.dmc.vo.PaymentVo;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 银行信息 服务实现类
 * </p>
 *
 * @
 * @since 2020-09-05
 */
@Service
@Transactional
public class CashOutOrderServiceImpl implements CashOutOrderService {

    @Autowired
    private UserAccountService userAccountService;

    @Autowired
    private CashOutOrdersMapper cashOutOrdersMapper;

    @Resource
    private TUserAccountMapper tUserAccountMapper;

    @Resource
    private BenefitTransactionMapper benefitTransactionMapper;

    @Resource
    private SysConfigMapper sysConfigMapper;

    @Resource
    private UserMapper userMapper;

    @Resource
    private UserBankCardService userBankCardService;

    @Resource
    private BankInfoMapper bankInfoMapper;


    @Override
    public CashOutOrdersVo addCashOutOrder(CashOutOrdersVo vo) {
        Integer cashOutType = vo.getCashOutType();
        cashOutType = cashOutType == null?0:cashOutType;
        Long currUid = SessionUtil.getCurrUid();
        User byId = userMapper.getById(currUid);
        TUserAccount tUserAccount = userAccountService.initUserAccountByUserId(currUid);
        BigDecimal benefit = tUserAccount.getBenefit();
        Assert.isTrue(DecimalUtil.subArrayOriginalValue(benefit, vo.getAmmount()).compareTo(BigDecimal.ZERO)>=0,"账户金额,不足以提现");
        SysConfig config = new SysConfig();
        config.setConfigKey(Constant.CONFIG_KEY_TI_XIAN_SWITH);
        SysConfig sysConfig = sysConfigMapper.selectOne(config);
        boolean isOnline = sysConfig !=null && "1".equalsIgnoreCase(sysConfig.getConfigValue());
        BigDecimal ammount = vo.getAmmount();
        vo.getCashOutType();
        if(isOnline){
            config.setConfigKey(Constant.CONFIG_KEY_TI_XIAN_LIMIT);
            SysConfig sysConfigLimit = sysConfigMapper.selectOne(config);
            String configValue = sysConfigLimit.getConfigValue();
            isOnline = new BigDecimal(configValue).compareTo(ammount)>=0;
            if(cashOutType == 1){
                Assert.isTrue(isOnline,"您的提现金额过大，请选择提现到银行卡");
            }else{
                vo.setMessage("大额提现需要平台审核，请耐心等待平台处理");
            }
        }
        //校验是否可以提现金额
        vo.setUserId(currUid);
        vo.setCreateTime(new Date());
        //判断是否开启线上提现
        vo.setCashOutLineType(isOnline?0:1);
        vo.setOrderCode(OrderCodeUtil.getCashOutOrderCode(currUid));
        vo.setStatus(0);
        config = new SysConfig();
        config.setConfigKey(Constant.CONFIG_KEY_CASH_OUT_RATE);
        SysConfig sysConfigRat = sysConfigMapper.selectOne(config);
        String cashOutRate = sysConfigRat.getConfigValue();
        cashOutRate = StringUtils.isBlank(cashOutRate)?"0":cashOutRate;
        BigDecimal transferCharge = DecimalUtil.mulArray(ammount, new BigDecimal(cashOutRate).divide(new BigDecimal(100)));
        vo.setTransferCharge(transferCharge);
        vo.setTransferChargeRate(new BigDecimal(cashOutRate).divide(new BigDecimal(100)));
        BigDecimal arriveAmmount = DecimalUtil.subArrayOriginalValue(ammount, transferCharge);
        vo.setArriveAmmount(arriveAmmount);
        CashOutOrders order = new CashOutOrders();
        BeanUtil.copyProperties(vo,order);
        cashOutOrdersMapper.insert(order);
        Message message=new Message();
        message.setUserId(-1L);
        message.setOrderId(order.getId());
        message.setOrderType(3);
        message.setType(3);
        message.setMessage(byId.getUsername()+"申请了提现,订单编号:"+order.getOrderCode());
        userAccountService.addUserMessage(message);
        if(isOnline){
            PayService payService = AbstractPayServiceImpl.getPayService(PayTypeDict.PAY_TYPE_WECHAT.getCn(), PayModeDict.PAY_MODE_MINI_APP.getCn());
            PaymentVo payment = new PaymentVo();
            payment.setPayModel(PayModeDict.PAY_MODE_MINI_APP.getCn());
            payment.setPayType(PayTypeDict.PAY_TYPE_WECHAT.getCn());
            String amount = arriveAmmount.multiply(new BigDecimal("100")).intValue()+"";
            payment.setAmount(amount);

            payment.setTransferType(cashOutType == 0?1:0);
            payment.setUserId(vo.getUserId());
            payment.setOrderId(order.getId()+"");

            payment.setOpenId(byId.getOpenId());
            payment.setOrderType(OrderTypeDict.ORDER_TYPE_TRANSFER.getCn());
            if(cashOutType == 1){
                BankCardVo bankCardVo=new BankCardVo();
                bankCardVo.setUserId(com.dmc.util.SessionUtil.getCurrUid());
                List<BankCardVo> userBankCardList=userBankCardService.getBankCardList(bankCardVo);
                Assert.isTrue(!CollectionUtils.isEmpty(userBankCardList),"无绑定银行卡信息");
                BankCardVo bankCard = userBankCardList.get(0);
                payment.setBankCardNum(bankCard.getCardId()+"");
                payment.setPayeeRealName(byId.getUsername());
                BankInfo bankInfo = bankInfoMapper.selectById(bankCard.getBankId());
                Assert.notNull(bankInfo,"无对应银行");
                payment.setBankCode(bankInfo.getBankCode());
            }
            RestRespResult<String> transfer = payService.transfer(payment);
            Integer code = transfer.getCode();
            Assert.isTrue(code == 200,"微信接口异常.提现失败");
            order.setStatus(2);
            cashStatus2(order);
            cashOutOrdersMapper.updateById(order);
            vo.setStatus(2);
        }
        return vo;
    }

    @Override
    public void updateCashOutOrder(CashOutOrdersVo vo) {
        Long id = vo.getId();
        Assert.notNull(id,"参数错误,请传输订单ID");
        CashOutOrders cashOutOrders = cashOutOrdersMapper.selectById(id);
        Assert.notNull(cashOutOrders,"参数错误,无当前提现订单");
        Integer status = cashOutOrders.getStatus();
        Assert.isTrue(status<2,"已提现,无法进行修改");
        BeanUtil.copyProperties(vo,cashOutOrders,CopyOptions.create().setIgnoreNullValue(true));
        cashStatus2(cashOutOrders);
        BigDecimal transferChargeRate = cashOutOrders.getTransferChargeRate() == null ? BigDecimal.ZERO : cashOutOrders.getTransferChargeRate();
        BigDecimal transferCharge = DecimalUtil.mulArray(cashOutOrders.getAmmount(),transferChargeRate);
        cashOutOrders.setTransferCharge(transferCharge);
        BigDecimal arriveAmmount = DecimalUtil.subArrayOriginalValue(cashOutOrders.getAmmount(), transferCharge);
        cashOutOrders.setArriveAmmount(arriveAmmount);
        cashOutOrdersMapper.updateById(cashOutOrders);
    }

    /**
     * 提现金额校验 以及当已提现时的处理
     * @param cashOutOrders
     */
    private void cashStatus2(CashOutOrders cashOutOrders){
        Long userId = cashOutOrders.getUserId();
        TUserAccount tUserAccount = userAccountService.initUserAccountByUserId(userId);
        BigDecimal benefit = tUserAccount.getBenefit();
        BigDecimal sub = DecimalUtil.subArrayOriginalValue(benefit, cashOutOrders.getAmmount());
        Assert.isTrue(sub.compareTo(BigDecimal.ZERO)>=0,"账户金额,不足以体现");
        if(cashOutOrders.getStatus()==2){
            cashOutOrders.setCashOutTime(new Date());
            //减收益
            tUserAccount.setBenefit(sub);
            tUserAccountMapper.updateById(tUserAccount);
            BenefitTransaction bt = new BenefitTransaction();
            bt.setCreateTime(new Date());
            bt.setType(BenefitTranTypeDict.BENEFIT_TRAN_TYPE_500.getCn());
            bt.setDes("提现收益");
            bt.setOrderId(cashOutOrders.getId());
            bt.setCurrentTotalBenefit(sub);
            bt.setBenefit(cashOutOrders.getAmmount().negate());
            //获取此类型当前收益总额
            List<Integer> typeList = new ArrayList<>();
            typeList.add(BenefitTranTypeDict.BENEFIT_TRAN_TYPE_500.getCn());
            BigDecimal sumType = benefitTransactionMapper.getSumByTypeList(userId,typeList);
            bt.setCurrentTypeBenefit(DecimalUtil.addArray(bt.getBenefit(),sumType));
            bt.setUserId(cashOutOrders.getUserId());
            benefitTransactionMapper.insert(bt);
        }

    }

    @Override
    public DataTable<CashOutOrdersVo> getCashOutOrderList(CashOutOrdersVo vo) {
        Integer start = vo.getStart();
        if(start == null){
            vo.setStart(0);
        }
        Integer length = vo.getLength();
        if(length == null){
            vo.setLength(10);
        }
        String userName = vo.getUserName();
        if(StringUtils.isNotBlank(userName)){
            vo.setUserName("%"+userName.trim()+"%");
        }
        String userPhone = vo.getUserPhone();
        if(StringUtils.isNotBlank(userPhone)){
            vo.setUserPhone("%"+userPhone.trim()+"%");
        }
        PageHelper.startPage(vo.getStart(), vo.getLength());
        List<CashOutOrdersVo> list =  cashOutOrdersMapper.getCashOutOrderList(vo);
        DataTable<CashOutOrdersVo> tables = new DataTable<>();
        tables.setRecordsTotal(((Page) list).getTotal());
        tables.setRecordsFiltered(tables.getRecordsTotal());
        tables.setDraw(vo.getDraw());
        tables.setData(list);
        return tables;
    }
}
